
export class RandomPseudo {
    public seed: number;

    constructor(seed: number = 0, public seedKeeper?: { seed: number }) {
        this.seed = seed ? seed : Math.round(Math.random() * 65535);
        if (!seedKeeper) {
            this.seedKeeper = this
        }
    }

    /**
     * 随机返回正数或负数
     * @param num 
     * @returns 
     */
    randomSign(num: number) {
        return num * (this.random() > 0.5 ? 1 : -1)
    }
    /**
     * 返回0~1之间的随机小数
     */
    random(): number {
        this.seedKeeper.seed = (this.seedKeeper.seed * 9301 + 49297) % 233280;
        return this.seedKeeper.seed / 233280.0;
    }
    /**
     * 返回指定区间随机浮点数
     * @param min 
     * @param max 
     */
    public randomFloat(min: number = 0, max: number = 1): number {
        return min + this.random() * (max - min);
    }
    /**
     * 返回指定区间随机整数，不包含上限
     * @param min 
     * @param max 
     */
    public randomInt(min: number = 0, max: number = 233279): number {
        return Math.floor(this.random() * (max - min)) + min
    }
    /**
     * 返回指定区间随机整数，包含上下限
     * @param min 
     * @param max 
     */
    public randomIntInclusive(min: number = 0, max: number = 233279): number {
        return min + Math.floor(this.random() * (max - min + 1));
    }
    /**
     * 通过一个百分比概率，Roll出是否成功
     * @param rate 成功率 
     */
    inRollPercent(rate: number) {
        return rate >= Math.ceil(this.random() * 100)
    }
    /**
     * 返回列表中随机一个元素
     * @param list
     */
    randomElementFromList = <T>(list: T[], removeElementFromList: boolean = false): T => {
        const index = this.randomIntInclusive(0, list.length - 1)
        const result = list[index]
        if (removeElementFromList) {
            list.splice(index, 1)
        }
        return result
    }
    /**返回列表中随机n个元素 */
    randomElementsFromList = <T>(list: T[], n: number, removeElementFromList: boolean = false): T[] => {
        list = list.slice()
        const result = []
        for (let index = 0; index < Math.min(n, list.length); index++) {
            result.push(this.randomElementFromList(list, removeElementFromList))
        }
        return result
    }

    /**
    * 返回列表中随机一个元素
    * @param list
    */
    randomElementFromWeightList = <T>(list: { value: T, weight: number }[], totalWeight = 0, removeElementFromList: boolean = false): { value: T, weight: number } => {
        if (!totalWeight) {
            totalWeight = list.reduce((p, c) => { return p + c.weight }, 0)
        }
        const random = this.randomInt(0, totalWeight)
        let accRate = 0

        let result = null
        for (let index = 0; index < list.length; index++) {
            const item = list[index];
            accRate += item.weight
            if (random < accRate) {
                result = item
                if (removeElementFromList) {
                    list.splice(index, 1)
                }
                break
            }
        }


        return result
    }

    /**随机打乱列表 */
    shuffle<T>(list: T[]): T[] {
        const result = list.slice()
        for (let i = 0; i < result.length; i++) {
            const j = this.randomIntInclusive(0, i)
            const temp = result[i]
            result[i] = result[j]
            result[j] = temp
        }
        return result
    }
}